package com.culturalCenter.dataCenter.schedule.training;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.culturalCenter.dataCenter.Utils.ClassUtil;
import com.culturalCenter.dataCenter.Utils.RedisUtil;
import com.culturalCenter.dataCenter.customEntity.ServicedNumber;
import com.culturalCenter.dataCenter.customEntity.training.pull.*;
import com.culturalCenter.dataCenter.entity.training.*;
import com.culturalCenter.dataCenter.mapper.training.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

/**
 * 定时任务_培训_拉取
 *
 * @author colors
 * @date 2021/3/3 11:58
 */
@Component
@Slf4j
@Async("dataThreadExecutor")
public class TrainingDataPull {

    @Resource
    private RestTemplate restTemplate;
    @Resource
    private TrainingMapper trainingMapper;
    @Resource
    private TrainingProjectMapper trainingProjectMapper;
    @Resource
    private TrainingCommentMapper trainingCommentMapper;
    @Resource
    private TrainingPeriodsMapper trainingPeriodsMapper;
    @Resource
    private TrainingApplyMapper trainingApplyMapper;
    @Resource
    private TrainingSignInMapper trainingSignInMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedissonClient redisson;
    private final long size = 200;
    private String requestUrl = "https://www.gz-arts.com/api/tcc-mes-service/client-api/culture/train";//https://tcc-test.interlib.com.cn
    private long training_timestamp1;
    private long training_timestamp2;
    private long training_timestamp3;
    private long training_timestamp4;
    private long training_timestamp5;
    private long training_timestamp6;

    /**
     * 初始化时间戳
     */
    @PostConstruct
    public void initTimestamp() {
        training_timestamp1 = !redisUtil.redisTemplate.hasKey("training_timestamp1") ? 0 : Long.parseLong(redisUtil.get("training_timestamp1"));
        training_timestamp2 = !redisUtil.redisTemplate.hasKey("training_timestamp2") ? 0 : Long.parseLong(redisUtil.get("training_timestamp2"));
        training_timestamp3 = !redisUtil.redisTemplate.hasKey("training_timestamp3") ? 0 : Long.parseLong(redisUtil.get("training_timestamp3"));
        training_timestamp4 = !redisUtil.redisTemplate.hasKey("training_timestamp4") ? 0 : Long.parseLong(redisUtil.get("training_timestamp4"));
        training_timestamp5 = !redisUtil.redisTemplate.hasKey("training_timestamp5") ? 0 : Long.parseLong(redisUtil.get("training_timestamp5"));
        training_timestamp6 = !redisUtil.redisTemplate.hasKey("training_timestamp6") ? 0 : Long.parseLong(redisUtil.get("training_timestamp6"));

        // for test
        // training_timestamp1 = 0;
        // training_timestamp2 = 0;
        // training_timestamp3 = 0;
        // training_timestamp4 = 0;
        // training_timestamp5 = 0;
        // training_timestamp6 = 0;
        // for (int i = 1; i <= 7; i++) {
        //     redisUtil.del("training_lock" + i);
        // }
    }

    /**
     * 获取返回数据中的data
     */
    public String getResponse(String uri, Map<String, Object> param) {
        try {
            String url = requestUrl + uri + "?" + ClassUtil.setParamString(param);
            String responseJson = restTemplate.getForObject(url, String.class, param);
            return JSON.parseObject(responseJson).getString("data");
        } catch (HttpServerErrorException e) {
            log.error("TCC综合管理平台服务端异常，请联系TCC相关人员");
            throw e;
        }
    }

    /**
     * 课程（cdc_training）
     */
//    @Scheduled(cron = "${cron.trainingPull}")
//     @Scheduled(cron = "${cron.test}")
    public void updateTrainingInfo() {
        String lockKey = "training_lock1";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("cdc_training开始拉取");

            List<Training> trainingList = new ArrayList<>();
            Map<String, Object> params = new HashMap<>();
            params.put("updateTimestamp", training_timestamp1);
            params.put("size", size);
            long pages = 1;
            for (long current = 1; current < pages + 1; current++) {
                params.put("current", current);
                String data = getResponse("/listPage", params);
                pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
                List<TrainingEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"), TrainingEntity.class);
                if (CollectionUtils.isNotEmpty(dataList)) {
                    for (TrainingEntity dataElement : dataList) {
                        Training training = new Training();
                        training.setId(UUID.randomUUID().toString());
                        training.setRefId(String.valueOf(dataElement.getId()));
                        training.setBranchId(String.valueOf(dataElement.getOrgId()));
                        training.setBranchName(dataElement.getOrgName());
                        if (dataElement.getProjectId() != null) {
                            training.setTrainingProjectId(dataElement.getProjectId().toString());
                        }
                        training.setTrainingName(dataElement.getTitle());
                        training.setPicture(dataElement.getCoverImg());
                        training.setTrainingLabel(dataElement.getLabels());
                        training.setClassify(dataElement.getCategoryName());
                        training.setDepartment(dataElement.getDepartmentName());
                        training.setOrganizationalUnit(dataElement.getOrgUnit());
                        training.setAddress(dataElement.getAddress());
                        training.setTotalNum(dataElement.getTotalQuota());
                        training.setCrowd(String.join(",", dataElement.getServicePerson()));
                        training.setContacts(dataElement.getPrincipalName());
                        training.setMobile(dataElement.getPrincipalPhone());
                        training.setPublishTime(dataElement.getPublishTime());
                        training.setSignUpBeginTime(dataElement.getRegisterStartTime());
                        training.setSignUpEndTime(dataElement.getRegisterEndTime());
                        training.setTrainingBeginTime(dataElement.getStartTime());
                        training.setTrainingEndTime(dataElement.getEndTime());
                        training.setSignInType(dataElement.getSignInType());
                        training.setSexLimit(dataElement.getSexRestriction());
                        training.setAgeLimit(dataElement.getAgeRestriction());
                        if (dataElement.getAgeMin() != null) {
                            training.setAgeMin(dataElement.getAgeMin());
                        }
                        if (dataElement.getAgeMax() != null) {
                            training.setAgeMax(dataElement.getAgeMax());
                        }
                        training.setTrainingType(dataElement.getRegisterTag());
                        training.setCreateBy(dataElement.getCreateBy());
                        training.setTotalPeriod(dataElement.getRoundCount());
                        training.setViewCount(dataElement.getViewCount());
                        training.setLikeCount(dataElement.getLikeCount());
                        training.setCollectCount(dataElement.getCollectCount());
                        training.setClassContent(dataElement.getTrainInfo());
                        training.setUpdateTime(dataElement.getUpdateTime());
                        training.setDataStatus(dataElement.getDelTag());
                        trainingList.add(training);
                    }
                    trainingMapper.insertBatch(trainingList);
                    redisUtil.set("training_timestamp1",
                            Long.toString(trainingList.stream().max(Comparator.comparing(Training::getUpdateTime)).get().getUpdateTime().getTime()));
                    trainingList.clear();
                }
            }

            log.info("*****************cdc_training拉取完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 项目（cdc_training_project）
     */
//    @Scheduled(cron = "${cron.trainingPull}")
    // @Scheduled(cron = "${cron.test}")
    public void updateTrainingProjectInfo() {
        String lockKey = "training_lock2";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("cdc_training_project开始拉取");

            List<TrainingProject> trainingProjectList = new ArrayList<>();
            Map<String, Object> params = new HashMap<>();
            params.put("updateTimestamp", training_timestamp2);
            params.put("size", size);
            long pages = 1;
            for (long current = 1; current < pages + 1; current++) {
                params.put("current", current);
                String data = getResponse("/project/listPage", params);
                pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
                List<TrainingProjectEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"), TrainingProjectEntity.class);
                if (CollectionUtils.isNotEmpty(dataList)) {
                    for (TrainingProjectEntity dataElement : dataList) {
                        TrainingProject trainingProject = new TrainingProject();
                        trainingProject.setId(UUID.randomUUID().toString());
                        trainingProject.setRefId(String.valueOf(dataElement.getId()));
                        trainingProject.setProjectName(dataElement.getTitle());
                        trainingProject.setPhoto(dataElement.getCoverImg());
                        trainingProject.setUpdateTime(dataElement.getUpdateTime());
                        trainingProjectList.add(trainingProject);
                    }
                    trainingProjectMapper.insertBatch(trainingProjectList);
                    redisUtil.set("training_timestamp2",
                            Long.toString(trainingProjectList.stream().max(Comparator.comparing(TrainingProject::getUpdateTime)).get().getUpdateTime().getTime()));
                    trainingProjectList.clear();
                }
            }

            log.info("*****************cdc_training_project拉取完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 课程期数（cdc_training_periods）
     */
//    @Scheduled(cron = "${cron.trainingPull}")
    // @Scheduled(cron = "${cron.test}")
    public void updateTrainingPeriod() {
        String lockKey = "training_lock3";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("cdc_training_periods开始拉取");

            List<TrainingPeriods> trainingPeriodsList = new ArrayList<>();
            Map<String, Object> params = new HashMap<>();
            params.put("updateTimestamp", training_timestamp3);
            params.put("size", size);
            long pages = 1;
            for (long current = 1; current < pages + 1; current++) {
                params.put("current", current);
                String data = getResponse("/period/listPage", params);
                pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
                List<TrainingPeriodEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"), TrainingPeriodEntity.class);
                if (CollectionUtils.isNotEmpty(dataList)) {
                    for (TrainingPeriodEntity dataElement : dataList) {
                        TrainingPeriods trainingPeriods = new TrainingPeriods();
                        trainingPeriods.setId(UUID.randomUUID().toString());
                        trainingPeriods.setRefId(String.valueOf(dataElement.getId()));
                        trainingPeriods.setTrainingId(String.valueOf(dataElement.getCourseId()));
                        trainingPeriods.setClassroomId(String.valueOf(dataElement.getClassroomId()));
                        trainingPeriods.setPlaceNo(dataElement.getPlaceNo());
                        trainingPeriods.setQuota(dataElement.getQuota());
                        trainingPeriods.setClassPeriod(dataElement.getClassPeriod());
                        trainingPeriods.setPeriodsName(dataElement.getTitle());
                        trainingPeriods.setBeginTime(dataElement.getStartTime());
                        trainingPeriods.setEndTime(dataElement.getEndTime());
                        trainingPeriods.setTeacherName(dataElement.getTeacherName());
                        trainingPeriods.setUpdateTime(dataElement.getUpdateTime());
                        trainingPeriods.setStatus(dataElement.getDelTag());
                        trainingPeriodsList.add(trainingPeriods);
                    }
                    trainingPeriodsMapper.insertBatch(trainingPeriodsList);
                    redisUtil.set("training_timestamp3",
                            Long.toString(trainingPeriodsList.stream().max(Comparator.comparing(TrainingPeriods::getUpdateTime)).get().getUpdateTime().getTime()));
                    trainingPeriodsList.clear();
                }
            }

            log.info("*****************cdc_training_periods拉取完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 评论（cdc_training_comment）
     */
//    @Scheduled(cron = "${cron.trainingPull}")
    // @Scheduled(cron = "${cron.test}")
    public void updateTrainingCommentInfo() {
        String lockKey = "training_lock4";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("cdc_training_comment开始拉取");

            List<TrainingComment> trainingCommentList = new ArrayList<>();
            Map<String, Object> params = new HashMap<>();
            params.put("updateTimestamp", training_timestamp4);
            params.put("size", size);
            long pages = 1;
            for (long current = 1; current < pages + 1; current++) {
                params.put("current", current);
                String data = getResponse("/listEvaluationRecords", params);
                if (data!=null){
                    pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
                    List<TrainingCommentEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"), TrainingCommentEntity.class);
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        for (TrainingCommentEntity dataElement : dataList) {
                            TrainingComment trainingComment = new TrainingComment();
                            trainingComment.setId(UUID.randomUUID().toString());
                            trainingComment.setRefId(String.valueOf(dataElement.getId()));
                            trainingComment.setTrainingId(String.valueOf(dataElement.getCourseId()));
                            trainingComment.setUserId(String.valueOf(dataElement.getUserId()));
                            trainingComment.setStar(dataElement.getStarLevel());
                            trainingComment.setContent(dataElement.getContent());
                            trainingComment.setReviewSituation(dataElement.getAuditStatus());
                            trainingComment.setCommentTime(dataElement.getEvaluationTime());
                            trainingComment.setUpdateTime(dataElement.getUpdateTime());
                            trainingCommentList.add(trainingComment);
                        }
                        trainingCommentMapper.insertBatch(trainingCommentList);
                        if (trainingCommentList.size()!=0){
                            redisUtil.set("training_timestamp4",
                                    Long.toString(trainingCommentList.stream().max(Comparator.comparing(TrainingComment::getUpdateTime)).get().getUpdateTime().getTime()));
                        }
                        trainingCommentList.clear();
                    }
                }
            }

            log.info("*****************cdc_training_comment拉取完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 录取记录（cdc_training_apply）
     */
//    @Scheduled(cron = "${cron.trainingPull}")
    // @Scheduled(cron = "${cron.test}")
    public void updateTrainingSignUpInfo() {
        String lockKey = "training_lock5";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("cdc_training_apply开始拉取");

            List<TrainingApply> trainSignUpList = new ArrayList<>();
            Map<String, Object> params = new HashMap<>();
            params.put("updateTimestamp", training_timestamp5);
            params.put("size", size);
            long pages = 1;
            for (long current = 1; current < pages + 1; current++) {
                params.put("current", current);
                String data = getResponse("/listEnrollRecords", params);
                pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
                List<TrainingSignUpEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"), TrainingSignUpEntity.class);
                if (CollectionUtils.isNotEmpty(dataList)) {
                    for (TrainingSignUpEntity dataElement : dataList) {
                        TrainingApply trainingApply = new TrainingApply();
                        trainingApply.setId(UUID.randomUUID().toString());
                        trainingApply.setRefId(String.valueOf(dataElement.getId()));
                        trainingApply.setTrainingId(String.valueOf(dataElement.getCourseId()));
                        trainingApply.setUserId(String.valueOf(dataElement.getUserId()));
                        trainingApply.setApplyTime(dataElement.getRegisterTime());
                        // trainingApply.setPlatform(trainingSignUpEntity.getEntranceSource());
                        // trainingApply.setLotStatus(trainingSignUpEntity.getLotStatus());
                        trainingApply.setUpdateTime(dataElement.getUpdateTime());
                        trainSignUpList.add(trainingApply);
                    }
                    trainingApplyMapper.insertBatch(trainSignUpList);
                    redisUtil.set("training_timestamp5",
                            Long.toString(trainSignUpList.stream().max(Comparator.comparing(TrainingApply::getUpdateTime)).get().getUpdateTime().getTime()));
                    trainSignUpList.clear();
                }
            }
            log.info("*****************cdc_training_apply拉取完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 签到（cdc_training_signIn）
     */
//    @Scheduled(cron = "${cron.trainingPull}")
    // @Scheduled(cron = "${cron.test}")
    public void pullTrainingSignInRecords() {
        String lockKey = "training_lock6";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("cdc_training_signIn开始拉取");

            List<TrainingSignIn> trainingSignIns = new ArrayList<>();
            Map<String, Object> params = new HashMap<>();
            params.put("updateTimestamp", training_timestamp6);
            params.put("size", size);
            long pages = 1;
            for (long current = 1; current < pages + 1; current++) {
                params.put("current", current);
                String data = getResponse("/listSignInRecords", params);
                pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
                List<TrainingSignIn> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"), TrainingSignIn.class);
                if (CollectionUtils.isNotEmpty(dataList)) {
                    trainingSignIns.addAll(dataList);
                    trainingSignInMapper.insertBatch(trainingSignIns);
                    redisUtil.set("training_timestamp6",
                            Long.toString(trainingSignIns.stream().max(Comparator.comparing(TrainingSignIn::getUpdateTime)).get().getUpdateTime().getTime()));
                    trainingSignIns.clear();
                }
            }
            log.info("*****************cdc_training_signIn拉取完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 拉取并统计服务人数(cdc_training_served_number)
     */
//    @Scheduled(cron = "${cron.trainingPull}")
    // @Scheduled(cron = "${cron.test}")
    public void pullServiceNumber() {
        String lockKey = "training_lock7";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("cdc_training_served_number开始拉取");

            /*
              获得branchId和date，然后根据这两个参数去请求获得数据
             */
            Map<String, Object> param = new HashMap<>();
            // 库里没数据(第一次)拉所有的，否则只拉今天的
            List<ServicedNumber> dataList = trainingMapper.getBranchDays(trainingMapper.countServicedNumber() == 0 ? null : DateUtil.today());
            dataList.forEach(data -> {
                String branchId = data.getBranchId();
                Date date = data.getDate();
                data.setOfflineNumber(trainingMapper.getOfflineNumberByBranchAndDay(branchId, DateUtil.formatDate(date)));
                param.put("startDate", DateUtil.formatDate(date));
                param.put("endDate", DateUtil.formatDate(DateUtil.offsetDay(date, 1)));
                param.put("orgId", branchId);
                String url = "https://www.gz-arts.com/api/tcc-mes-service/client-api/online/overview?" + ClassUtil.setParamString(param);
                String responseJson = restTemplate.getForObject(url, String.class, param);
                String result = JSON.parseObject(responseJson).getString("data");
                JSONObject jsonObject = JSON.parseObject(result);
                Map<String, Integer> servedMap = JSON.toJavaObject(jsonObject, Map.class);
                data.setOnlineNumber(servedMap.get("totalLearnCount"));
                trainingMapper.insertTrainingServedNumber(data);
            });

            log.info("cdc_training_served_number拉取完毕");
        } catch (HttpServerErrorException e) {
            log.error("TCC综合管理平台服务端异常，请联系TCC相关人员");
            throw e;
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

}
